﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Serialization
Imports System.Xml

Namespace System.Workflow.ComponentModel.Design
    <Serializable> _
    Friend Class WorkflowMarkupSerializationStore
        Inherits SerializationStore
        Implements ISerializable
        ' Methods
        Friend Sub New(ByVal serviceProvider As IServiceProvider)
            Me.activities = New List([Of] Activity)
            Me.parentObjectNameList = New List([Of] String)
            Me.memberList = New List([Of] MemberDescriptor)
            Me.serviceProvider = serviceProvider
        End Sub

        Private Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            Me.activities = New List([Of] Activity)
            Me.parentObjectNameList = New List([Of] String)
            Me.memberList = New List([Of] MemberDescriptor)
            Me.serializedXmlString = CStr(info.GetValue("XmlString", GetType(String)))
            Me.assemblies = DirectCast(info.GetValue("Assemblies", GetType(AssemblyName())), AssemblyName())
        End Sub

        Friend Sub AddMember(ByVal value As Object, ByVal member As MemberDescriptor)
            If (value Is Nothing) Then
                Throw New ArgumentNullException("value")
            End If
            If (member Is Nothing) Then
                Throw New ArgumentNullException("member")
            End If
            If (Not Me.serializedXmlString Is Nothing) Then
                Throw New InvalidOperationException(DR.GetString("InvalidOperationStoreAlreadyClosed", New Object(0  - 1) {}))
            End If
            Dim service As IReferenceService = [TryCast](Me.serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
            Me.parentObjectNameList.Add(service.GetName(value))
            Me.memberList.Add(member)
        End Sub

        Friend Sub AddObject(ByVal value As Object)
            If (Not Me.serializedXmlString Is Nothing) Then
                Throw New InvalidOperationException(DR.GetString("InvalidOperationStoreAlreadyClosed", New Object(0  - 1) {}))
            End If
            Dim item As Activity = [TryCast](value,Activity)
            If (item Is Nothing) Then
                Throw New ArgumentException("value")
            End If
            Me.activities.Add(item)
        End Sub

        Public Overrides Sub Close()
            If (Me.serializedXmlString Is Nothing) Then
                Dim manager As DesignerSerializationManager = New LocalDesignerSerializationManager(Me, Me.serviceProvider)
                [Using] manager.CreateSession
                    Dim serializationManager As New WorkflowMarkupSerializationManager(manager)
                    Dim w As New StringWriter(CultureInfo.InvariantCulture)
                    [Using] writer2 As XmlTextWriter = New XmlTextWriter(w)
                        If (Me.memberList.Count = 0) Then
                            Dim serializer As New WorkflowMarkupSerializer
                            Dim activity As Activity
                            For Each activity In Me.activities
                                serializer.SerializeObject(serializationManager, activity, writer2)
                            Next
                        Else
                            Dim provider As New PropertySegmentSerializationProvider
                            serializationManager.AddSerializationProvider(provider)
                            serializationManager.Context.Push(New StringWriter(CultureInfo.InvariantCulture))
                            Dim service As IReferenceService = [TryCast](Me.serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
                            If (Not service Is Nothing) Then
                                Dim i As Integer
                                For i = 0 To Me.memberList.Count - 1
                                    Dim reference As Object = service.GetReference(Me.parentObjectNameList.Item(i))
                                    Dim serializer2 As New PropertySegmentSerializer(Nothing)
                                    If TypeOf Me.memberList.Item(i) Is PropertyDescriptor Then
                                        Dim property As PropertyInfo = XomlComponentSerializationService.GetProperty(reference.GetType, [TryCast](Me.memberList.Item(i),PropertyDescriptor).Name, (BindingFlags.Public Or BindingFlags.Instance))
                                        If (Not [property] Is Nothing) Then
                                            serializer2.SerializeObject(serializationManager, New PropertySegment(Me.serviceProvider, reference, [property]), writer2)
                                        Else
                                            serializer2.SerializeObject(serializationManager, New PropertySegment(Me.serviceProvider, reference, [TryCast](Me.memberList.Item(i),PropertyDescriptor)), writer2)
                                        End If
                                    ElseIf TypeOf Me.memberList.Item(i) Is EventDescriptor Then
                                        Dim service2 As IEventBindingService = [TryCast](Me.serviceProvider.GetService(GetType(IEventBindingService)),IEventBindingService)
                                        If (Not service2 Is Nothing) Then
                                            Dim segment As New PropertySegment(Me.serviceProvider, reference, service2.GetEventProperty([TryCast](Me.memberList.Item(i),EventDescriptor)))
                                            serializer2.SerializeObject(serializationManager, segment, writer2)
                                        End If
                                    End If
                                Next i
                            End If
                            serializationManager.Context.Pop
                            serializationManager.RemoveSerializationProvider(provider)
                        End If
                    End [Using]
                    Me.serializedXmlString = w.ToString
                    Dim list As New List([Of] AssemblyName)
                    Dim activity2 As Activity
                    For Each activity2 In Me.activities
                        Dim assembly As Assembly = activity2.GetType.Assembly
                        list.Add([assembly].GetName(True))
                    Next
                    Me.assemblies = list.ToArray
                End [Using]
            End If
        End Sub

        Friend Function Deserialize(ByVal serviceProvider As IServiceProvider) As IList
            Dim list2 As IList
            Dim manager As DesignerSerializationManager = New LocalDesignerSerializationManager(Me, serviceProvider)
            [Using] manager.CreateSession
                Dim handler As EventHandler([Of] WorkflowMarkupElementEventArgs) = Nothing
                Dim list As New ArrayList
                Dim xomlSerializationManager As New WorkflowMarkupSerializationManager(manager)
                Dim reader As New XmlTextReader(Me.serializedXmlString, XmlNodeType.Element, Nothing)
                reader.MoveToElement
            Label_0042:
                If Not reader.Read Then
                    list2 = list
                Else
                    If (handler Is Nothing) Then
                        handler = Function (ByVal sender As Object, ByVal eventArgs As WorkflowMarkupElementEventArgs) 
                            If ((eventArgs.XmlReader.LookupNamespace(eventArgs.XmlReader.Prefix) = "http://schemas.microsoft.com/winfx/2006/xaml") AndAlso TypeOf xomlSerializationManager.Context.Current Is Activity) Then
                                WorkflowMarkupSerializationHelpers.ProcessDefTag(xomlSerializationManager, eventArgs.XmlReader, [TryCast](xomlSerializationManager.Context.Current,Activity), True, String.Empty)
                            End If
                        End Function
                    End If
                    AddHandler xomlSerializationManager.FoundDefTag, handler
                    Dim obj2 As Object = New WorkflowMarkupSerializer().DeserializeObject(xomlSerializationManager, reader)
                    If (obj2 Is Nothing) Then
                        Throw New InvalidOperationException(DR.GetString("InvalidOperationDeserializationReturnedNonActivity", New Object(0  - 1) {}))
                    End If
                    If TypeOf obj2 Is Activity Then
                        [TryCast](obj2,Activity).UserData.Remove(UserDataKeys.CustomActivity)
                    End If
                    list.Add(obj2)
                    goto Label_0042
                End If
            End [Using]
            Return list2
        End Function

        Friend Function Deserialize(ByVal serviceProvider As IServiceProvider, ByVal container As IContainer) As ICollection
            Throw New NotImplementedException
        End Function

        Friend Sub DeserializeTo(ByVal serviceProvider As IServiceProvider, ByVal container As IContainer)
            Dim manager As DesignerSerializationManager = New LocalDesignerSerializationManager(Me, serviceProvider)
            [Using] manager.CreateSession
                Dim serializationManager As New WorkflowMarkupSerializationManager(manager)
                Dim provider As New PropertySegmentSerializationProvider
                serializationManager.AddSerializationProvider(provider)
                Dim input As New StringReader(Me.serializedXmlString)
                [Using] reader2 As XmlTextReader = New XmlTextReader(input)
                    Do While (((reader2.NodeType <> XmlNodeType.Element) AndAlso (reader2.NodeType <> XmlNodeType.ProcessingInstruction)) AndAlso reader2.Read)
                    Loop
                    Dim service As IReferenceService = [TryCast](Me.serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
                    Dim service2 As IComponentChangeService = [TryCast](Me.serviceProvider.GetService(GetType(IComponentChangeService)),IComponentChangeService)
                    Dim i As Integer
                    For i = 0 To Me.memberList.Count - 1
                        Dim reference As Object = service.GetReference(Me.parentObjectNameList.Item(i))
                        If (Not reference Is Nothing) Then
                            Dim flag As Boolean = ((Not service2 Is Nothing) AndAlso (Not TypeOf reference Is IComponent OrElse (DirectCast(reference, IComponent).Site Is Nothing)))
                            Dim member As PropertyDescriptor = [TryCast](Me.memberList.Item(i),PropertyDescriptor)
                            If flag Then
                                service2.OnComponentChanging(reference, member)
                            End If
                            serializationManager.Context.Push(reference)
                            New PropertySegmentSerializer(Nothing).DeserializeObject(serializationManager, reader2)
                            serializationManager.Context.Pop
                            If flag Then
                                service2.OnComponentChanged(reference, member, Nothing, Nothing)
                            End If
                        End If
                    Next i
                End [Using]
                serializationManager.RemoveSerializationProvider(provider)
            End [Using]
        End Sub

        Public Overrides Sub Save(ByVal stream As Stream)
            Me.Close
            New BinaryFormatter().Serialize(stream, Me)
        End Sub

        Private Sub System.Runtime.Serialization.ISerializable.GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
            info.AddValue("XmlString", Me.serializedXmlString)
            info.AddValue("Assemblies", Me.assemblies)
        End Sub


        ' Properties
        Private ReadOnly Property AssemblyNames As AssemblyName()
            Get
                Return Me.assemblies
            End Get
        End Property

        Public Overrides ReadOnly Property Errors As ICollection
            Get
                Return Nothing
            End Get
        End Property


        ' Fields
        Private activities As List([Of] Activity)
        Private assemblies As AssemblyName()
        Private Const AssembliesKey As String = "Assemblies"
        Private memberList As List([Of] MemberDescriptor)
        Private parentObjectNameList As List([Of] String)
        Private serializedXmlString As String
        Private Const SerializedXmlString As String = "XmlString"
        Private serviceProvider As IServiceProvider

        ' Nested Types
        Private Class LocalDesignerSerializationManager
            Inherits DesignerSerializationManager
            ' Methods
            Friend Sub New(ByVal store As WorkflowMarkupSerializationStore, ByVal provider As IServiceProvider)
                MyBase.New(provider)
                Me.store = store
            End Sub

            Protected Overrides Function [GetType](ByVal name As String) As Type
                Dim type As Type = MyBase.GetType(name)
                If (type Is Nothing) Then
                    Dim index As Integer = name.IndexOf(",")
                    If (index <> -1) Then
                        name = name.Substring(0, index)
                    End If
                    Dim assemblyNames As AssemblyName() = Me.store.AssemblyNames
                    Dim name2 As AssemblyName
                    For Each name2 In assemblyNames
                        Dim assembly As Assembly = Assembly.Load(name2)
                        If (Not [assembly] Is Nothing) Then
                            type = [assembly].GetType(name)
                            If (Not type Is Nothing) Then
                                Exit For
                            End If
                        End If
                    Next
                    If (type Is Nothing) Then
                        Dim name3 As AssemblyName
                        For Each name3 In assemblyNames
                            Dim assembly2 As Assembly = Assembly.Load(name3)
                            If (Not assembly2 Is Nothing) Then
                                Dim name4 As AssemblyName
                                For Each name4 In assembly2.GetReferencedAssemblies
                                    Dim assembly3 As Assembly = Assembly.Load(name4)
                                    If (Not assembly3 Is Nothing) Then
                                        type = assembly3.GetType(name)
                                        If (Not type Is Nothing) Then
                                            Exit For
                                        End If
                                    End If
                                Next
                                If (Not type Is Nothing) Then
                                    Return type
                                End If
                            End If
                        Next
                    End If
                End If
                Return type
            End Function


            ' Fields
            Private store As WorkflowMarkupSerializationStore
        End Class
    End Class
End Namespace

